//! 不安全操作 (Unsafe Operations)
//!
//! Rust 的设计很大程度上是在保证内存安全和防止各种错误之间寻求平衡。
//! 但有些时候，这些保证会限制一些有效的代码实现。为此，Rust 提供了
//! `unsafe` 关键字来绕过这些保护措施。
//!
//! 不安全操作主要有以下五种场景：
//! 1. 解引用裸指针
//! 2. 调用不安全的函数或方法
//! 3. 访问或修改可变静态变量
//! 4. 实现不安全 trait
//! 5. 访问 union 的字段

use std::ptr::addr_of;
use std::sync::atomic::{AtomicU32, Ordering};

/// 1. 解引用裸指针 (Dereferencing Raw Pointers)
///
/// 裸指针是不安全的，因为它们：
/// - 允许忽略借用规则，可以同时拥有不可变和可变的指针指向同一数据
/// - 不保证指向有效的内存
/// - 允许为空
/// - 没有自动清理机制
pub fn dereferencing_raw_pointers() {
    println!("=== 解引用裸指针 (Dereferencing Raw Pointers) ===");

    let mut num = 5;

    // 创建裸指针
    let r1 = &num as *const i32; // 不可变裸指针
    let r2 = &mut num as *mut i32; // 可变裸指针

    // 在不安全块中解引用裸指针
    unsafe {
        println!("r1 指向的值: {}", *r1);
        println!("r2 指向的值: {}", *r2);

        // 修改通过可变裸指针指向的值
        *r2 = 10;
        println!("修改后 r1 指向的值: {}", *r1);
    }

    // 创建指向任意内存地址的裸指针（不安全）
    let address = 0x012345usize;
    let _r = address as *const i32;

    // 注意：解引用这样的指针会导致未定义行为
    // unsafe {
    //     println!("地址 {} 的值: {}", address, *_r);
    // }
}

/// 2. 调用不安全函数 (Calling Unsafe Functions)
///
/// 不安全函数是指那些需要手动保证内存安全的函数
pub fn calling_unsafe_functions() {
    println!("\n=== 调用不安全函数 (Calling Unsafe Functions) ===");

    unsafe fn dangerous() {
        println!("这是一个不安全函数");
    }

    // 调用不安全函数需要在不安全块中进行
    unsafe {
        dangerous();
    }
}

/// 3. 创建不安全代码的安全抽象
///
/// 最好的不安全代码实践是将其封装在安全的 API 中
pub fn safe_abstractions() {
    println!("\n=== 创建不安全代码的安全抽象 ===");

    // 示例：实现一个安全的函数，内部使用不安全代码
    fn split_at_mut<T>(slice: &mut [T], mid: usize) -> (&mut [T], &mut [T]) {
        let len = slice.len();
        let ptr = slice.as_mut_ptr();

        assert!(mid <= len);

        unsafe { (std::slice::from_raw_parts_mut(ptr, mid), std::slice::from_raw_parts_mut(ptr.add(mid), len - mid)) }
    }

    let mut vector = vec![1, 2, 3, 4, 5, 6];
    let (left, right) = split_at_mut(&mut vector, 3);

    println!("左半部分: {:?}", left);
    println!("右半部分: {:?}", right);
}

/// 4. 使用 extern 函数调用外部代码
///
/// 使用 extern 关键字来调用其他语言编写的函数
pub fn extern_functions() {
    println!("\n=== 使用 extern 函数调用外部代码 ===");

    // 声明一个外部 C 函数
    unsafe extern "C" {
        fn abs(input: i32) -> i32;
    }

    unsafe {
        println!("绝对值 -3: {}", abs(-3));
    }

    // 创建一个可以被 C 代码调用的函数
    #[unsafe(no_mangle)]
    pub extern "C" fn call_from_c() {
        println!("Rust 函数被 C 代码调用");
    }
}

/// 5. 访问或修改可变静态变量
///
/// 全局状态很难管理，可能导致竞争条件
/// 现代Rust推荐使用原子类型或同步原语替代可变静态变量
///
/// 不安全的方式（Rust 2024中不推荐）:
/// ```rust
/// static mut COUNTER: u32 = 0;
///
/// fn unsafe_example() {
///     unsafe {
///         // 在Rust 2024之前这种方式可行，但现在不推荐
///         COUNTER += 1;
///         // println!("计数器值: {}", COUNTER); // 这会产生编译错误
///     }
/// }
/// ```
///
/// 推荐的安全方式:
pub fn mutable_static_variables() {
    println!("\n=== 访问或修改可变静态变量 ===");

    // 使用原子类型替代可变静态变量，这是更安全的方式
    static COUNTER: AtomicU32 = AtomicU32::new(0);

    fn increment_counter() {
        // 原子操作，线程安全
        let new_value = COUNTER.fetch_add(1, Ordering::SeqCst) + 1;
        println!("计数器值: {}", new_value);
    }

    increment_counter();
    increment_counter();
    increment_counter();

    // 获取最终值
    println!("最终计数器值: {}", COUNTER.load(Ordering::SeqCst));
}

/// 6. 实现不安全 trait
///
/// 不安全 trait 是那些编译器无法验证的 trait
pub fn implementing_unsafe_traits() {
    println!("\n=== 实现不安全 trait ===");

    // 示例：实现 Send 和 Sync trait
    // 这些是特殊的不安全 trait，通常由编译器自动实现

    // 对于大多数类型，Rust 会自动实现 Send 和 Sync
    // 但对于包含原始指针或需要特殊处理的类型，可能需要手动实现

    // unsafe impl Send for MyType {}
    // unsafe impl Sync for MyType {}

    println!("Send trait 表示类型的所有权可以在线程间传递");
    println!("Sync trait 表示类型可以安全地在线程间共享引用");
}

/// 7. 访问 union 的字段
///
/// union 是一种特殊的类型，允许在相同内存位置存储不同类型的值
pub fn accessing_unions() {
    println!("\n=== 访问 union 的字段 ===");

    #[repr(C)]
    union MyUnion {
        i: i32,
        f: f32,
    }

    let u = MyUnion { i: 42 };

    unsafe {
        println!("作为整数访问: {}", u.i);
        // 注意：访问 f 可能导致未定义行为，因为我们存储的是 i
        // println!("作为浮点数访问: {}", u.f);
    }
}

/// 8. 何时使用不安全代码
///
/// 不安全代码的使用场景和最佳实践
pub fn when_to_use_unsafe() {
    println!("\n=== 何时使用不安全代码 ===");

    println!("合理的使用场景:");
    println!("1. 与操作系统交互");
    println!("2. 实现编程语言的运行时");
    println!("3. 调用 C 语言库");
    println!("4. 实现某些高性能数据结构");
    println!("5. 与硬件交互");

    println!("\n不安全代码不代表不正确代码，它只是表示:");
    println!("- 编译器没有提供内存安全保证");
    println!("- 需要程序员手动保证内存安全");
    println!("- 可能导致未定义行为");
}

/// 主演示函数
pub fn demonstrate_unsafe_operations() {
    dereferencing_raw_pointers();
    calling_unsafe_functions();
    safe_abstractions();
    extern_functions();
    mutable_static_variables();
    implementing_unsafe_traits();
    accessing_unions();
    when_to_use_unsafe();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_dereferencing_raw_pointers() {
        let mut num = 5;
        let r1 = &num as *const i32;
        let r2 = &mut num as *mut i32;

        unsafe {
            assert_eq!(*r1, 5);
            assert_eq!(*r2, 5);
            *r2 = 10;
            assert_eq!(*r1, 10);
        }
    }

    #[test]
    fn test_calling_unsafe_functions() {
        unsafe fn dangerous() -> i32 {
            42
        }

        unsafe {
            assert_eq!(dangerous(), 42);
        }
    }

    #[test]
    fn test_safe_abstractions() {
        // 将split_at_mut函数定义复制到测试中
        fn split_at_mut<T>(slice: &mut [T], mid: usize) -> (&mut [T], &mut [T]) {
            let len = slice.len();
            let ptr = slice.as_mut_ptr();

            assert!(mid <= len);

            unsafe { (std::slice::from_raw_parts_mut(ptr, mid), std::slice::from_raw_parts_mut(ptr.add(mid), len - mid)) }
        }

        let mut vector = vec![1, 2, 3, 4, 5, 6];
        let (left, right) = split_at_mut(&mut vector, 3);
        assert_eq!(left, &[1, 2, 3]);
        assert_eq!(right, &[4, 5, 6]);
    }

    #[test]
    fn test_mutable_static_variables() {
        use std::sync::atomic::{AtomicU32, Ordering};

        static COUNTER: AtomicU32 = AtomicU32::new(0);

        let old_value = COUNTER.fetch_add(1, Ordering::SeqCst);
        let current_value = COUNTER.load(Ordering::SeqCst);

        assert_eq!(current_value, old_value + 1);
    }

    #[test]
    fn test_demonstrate_unsafe_operations() {
        demonstrate_unsafe_operations();
    }
}
